package com.mgq.generic;

import java.util.ArrayList;
import java.util.List;

/**
 * @author MaGuangQi
 * 类型通配符 ? 例如 showBox中泛型是Number类型时,我们无法使用Integer类型
 * 这时我们就可以通过类型通配符来解决
 * @date 2021-12-24 17:24
 **/
public class TypeGeneric {
    public static void main(String[] args) {
        Box<Number> box1 = new Box<>(100);
        showBox(box1);
        Box<Integer> box2 = new Box<>(200);
        showBox(box2);

        List<Animal> animals = new ArrayList<>();
        List<Cat> cats = new ArrayList<>();
        List<MiniCat> miniCats = new ArrayList<>();
        //---------------上限------------------------------
        //showAnimalUp(animals);
        showAnimalUp(cats);
        showAnimalUp(miniCats);

        //---------------下限------------------------------
        showAnimalDown(animals);
        showAnimalDown(cats);

        //showAnimalDown(miniCats);

    }

    /*public static void showBox(Box<Number> box) {
        Number first = box.getFirst();
        System.out.println(first);
    }*/
    /*public static void showBox(Box<?> box) {
        Object first = box.getFirst();
        System.out.println(first);
    }*/

    /**
     * 类型通配符的上限
     * @param box
     */
    public static void showBox(Box<? extends Number> box) {
        Object first = box.getFirst();
        System.out.println(first);
    }

    /**
     * 类型通配符的上限 只能是cat或者是cat的子类
     * @param cats
     */
    public static void showAnimalUp(List<? extends Cat> cats) {
        for (Cat cat : cats) {
            System.out.println(cat);
        }
    }

    /**
     * 类型通配符的下限 只能是cat或者是cat的父类
     * @param cats
     */
    public static void showAnimalDown(List<? super Cat> cats) {
        for (Object cat : cats) {
            System.out.println(cat);
        }
    }
}

class Box<T>{
    private T first;

    public Box(T first) {
        this.first = first;
    }

    public T getFirst() {
        return first;
    }

    public void setFirst(T first) {
        this.first = first;
    }
}
